/* main.c

Copyright (C) Alex S. (mailto: md5sum@alexsp.ru)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details
http://www.gnu.org/licenses/gpl-2.0.html.

You should have received a copy of the GNU General Public License
along with this program in the file gpl-2.0.txt;
if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <avr/io.h>
#include "hardware.h"
#include "ds1820.h"
#include "hp03.h"
#include "glcd.h"
#include "m41t81.h"
#include "eep.h"
#include "menu.h"
#if HUMIDITY==21
#include "sht21.h"
#endif
#if HUMIDITY==10
#include "sht10.h"
#endif

hw_ret_status term1_lasterr,term2_lasterr,hop_lasterr,clock_lasterr,sht_lasterr;
#define HALF_CLK_ARR_SIZE 15
uint16_t half_clock_pressure[HALF_CLK_ARR_SIZE];
int8_t	half_clock_t1[HALF_CLK_ARR_SIZE];
int8_t	half_clock_t2[HALF_CLK_ARR_SIZE];
uint8_t half_clock_index=0;

uint16_t press_10_sec[12];
int8_t term1_10_sec[12];
int8_t term2_10_sec[12];
uint8_t ten_sec_index=0;
uint8_t ten_last_index=0;

uint8_t hw_flags=Press_OK|Termo1_OK|Termo2_OK;
uint8_t new_half_val=1;
uint8_t first_measure=1;
uint8_t redrawall=0;
#if HUMIDITY>0
uint8_t sht_rh=0;
int8_t sht_t=0;
#endif


void set_10_sec_avg();
void set_half_clock_avg();

int main() {

	uint8_t last_time_position=255;
	uint8_t i;
	uint8_t key;
	uint8_t current_led_pwr;

#if USE_Watchdog==1
	wdt_enable(WATCHDOG_TIME);
#endif
	lcd_backlight_on(2);

	while ((clock_lasterr=time_init())!=SUCCESS) {}
	//hw_flags&=~Timer_OK;
	sec_flag=0;
	sei();
	while (sec_flag==0) {}
	sec_flag=0;
	while ((clock_lasterr=time_read())!=SUCCESS) {}
		//hw_flags&=~Timer_OK;
	if ((term1_lasterr=ds1820_start(DS1820_1))!=SUCCESS) hw_flags&=~Termo1_OK;
	if ((term2_lasterr=ds1820_start(DS1820_2))!=SUCCESS) hw_flags&=~Termo2_OK;
	if ((hop_lasterr=HOP03_init())!=SUCCESS) hw_flags&=~Press_OK;
#if HUMIDITY==10
	SHT10_softreset();
	sht_lasterr=SUCCESS;
#endif

	if (arrays_init()) {
		for (i=0;i<HALF_CLK_ARR_SIZE;i++) {
			half_clock_pressure[i]=ram_array[time.position].pressure;
			half_clock_t1[i]=ram_array[time.position].term1;
			half_clock_t2[i]=ram_array[time.position].term2;
		}
		new_half_val=0;
	}
	GLCD_init();
	lcd_backlight_on(led_power_max);
	current_led_pwr=led_power_max;
	led_time_left=led_time;


#if USE_Watchdog==1
	wdt_reset();
#endif

	for (;;) {
#if USE_Watchdog==1
		wdt_reset();
#endif
		key=check_keys();
		if (key) {
			if (display_mode==DISPLAY_MENU) {menu(key);}
			else{
				if (key==(KEY_PLUS|KEY_MINUS)) {
					current_led_pwr=led_power_max;
					led_time_left=0;
					lcd_backlight_on(current_led_pwr);
					display_mode=DISPLAY_MENU;
					menu(key);
				}
				else if (key==(KEY_ENTER|KEY_CHANGE)) {
					if (current_led_pwr<led_power_max) {
						current_led_pwr=led_power_max;
						led_time_left=led_time;
					}else{
						current_led_pwr=led_power_min;
						led_time_left=0;
					}
					lcd_backlight_on(current_led_pwr);
				}
				else if ((key==KEY_ENTER)&&(current_led_pwr!=0)) {
					led_time_left=0;
					current_led_pwr=0;
					lcd_backlight_on(0);
				}
				else if (key==DOUBLE_ENTER) {
					current_led_pwr=led_power_max;
					led_time_left=led_time;
					lcd_backlight_on(current_led_pwr);
					if (display_mode==DISPLAY_PRESSURE) {
						display_mode=DISPLAY_CLOCK;
						GLCD_clear();
						print_temp(term1_10_sec[ten_last_index],0,term1_lasterr);
						print_temp(term2_10_sec[ten_last_index],1,term2_lasterr);
#if HUMIDITY>0
						print_humidity(sht_rh,sht_t,sht_lasterr);
#endif /* HUMIDITY */
					}
					else if (display_mode==DISPLAY_CLOCK) {
						display_mode=DISPLAY_PRESSURE;
						GLCD_clear();
						print_pressure(press_10_sec[ten_last_index]);
						print_temp(term1_10_sec[ten_last_index],0,term1_lasterr);
						print_temp(term2_10_sec[ten_last_index],1,term2_lasterr);
#if HUMIDITY>0
						print_humidity(sht_rh,sht_t,sht_lasterr);
#endif /* HUMIDITY */

					}
				}
			}
		}

		if (sec_flag>0){
			time.sec++;
			if (time.sec==60) time.sec=0;
			time.unix_time++;
			GLCD_print_time();
			if (first_measure) {
				set_10_sec_avg();
				set_half_clock_avg();
				last_time_position=time.position;
				save_eep=(void *)&eep_array[time.position];
				save_ram=(void *)&ram_array[time.position];
			}
			if (!(time.sec % 10)) set_10_sec_avg();
#if HUMIDITY==10
			if ((time.sec % 10)==8) {
				if (sht_lasterr==CRC) {SHT10_softreset();_delay_ms(20);}
				sht_lasterr=SHT10_startT();
			}
#endif
			if ((time.sec % 10)==9) {
				if ((term1_lasterr=ds1820_start(DS1820_1))!=SUCCESS) hw_flags&=~Termo1_OK;
				if ((term2_lasterr=ds1820_start(DS1820_2))!=SUCCESS) hw_flags&=~Termo2_OK;
#if HUMIDITY==10
				if (sht_lasterr==SUCCESS) sht_lasterr=SHT10_calc_T();
				if (sht_lasterr==CRC) {SHT10_softreset();_delay_ms(20);}
				sht_lasterr=SHT10_startH();
#endif
			}
			if (time.sec==0) {
				while (time_read()!=SUCCESS) {}
					//hw_flags&=~Timer_OK;
				GLCD_print_time();
				if (last_time_position!=time.position) {
					if (last_time_position<NUM_POINT) eeprom_write_block((void *)save_ram,(void *)save_eep,sizeof(value_array_t));
					last_time_position=time.position;
					save_eep=(void *)&eep_array[time.position];
					save_ram=(void *)&ram_array[time.position];
				}
				if (!(time.min %2)) set_half_clock_avg();
			}
			sec_flag--;
			if (led_time_left>0) {
				led_time_left--;
				if (led_time_left==0) {
					current_led_pwr=led_power_min;
					lcd_backlight_on(current_led_pwr);
				}
			}
			if (redrawall==1){
				redrawall=0;
				current_led_pwr=led_power_max;
				led_time_left=led_time;
				print_pressure(press_10_sec[ten_sec_index-1]);
				print_temp(term1_10_sec[ten_sec_index-1],0,term1_lasterr);
				print_temp(term2_10_sec[ten_sec_index-1],1,term2_lasterr);
			}
		}
		parse_cmd();
	}
	return 0;
}

void set_10_sec_avg() {
	double press,hop_temp;
	int16_t temperature;
	uint8_t errors;

	if ((hop_lasterr=HOP03_get_value(&press,&hop_temp))!=SUCCESS) {
		hw_flags&=~Press_OK;
		press_10_sec[ten_sec_index]=press_10_sec[(ten_sec_index>0?ten_sec_index-1:11)];
	}else{
		press_10_sec[ten_sec_index]=press*10;
	}

	errors=5;
	while (((term1_lasterr=ds1820_get_temp(DS1820_1,&temperature))!=SUCCESS)&&(errors>0)){
		errors--;
	}
	if (term1_lasterr!=SUCCESS)	{
		hw_flags&=~Termo1_OK;
		term1_10_sec[ten_sec_index]=term1_10_sec[(ten_sec_index>0?ten_sec_index-1:11)];
	}else {
		term1_10_sec[ten_sec_index]=temperature/2;
		if (temperature==85*2) {
			if ((term1_10_sec[(ten_sec_index>0?ten_sec_index-1:11)]<70)||(term1_10_sec[(ten_sec_index>0?ten_sec_index-1:11)]>100)) {
				term1_10_sec[ten_sec_index]=term1_10_sec[(ten_sec_index>0?ten_sec_index-1:11)];
			}
		}
	}

	errors=5;
	while (((term2_lasterr=ds1820_get_temp(DS1820_2,&temperature))!=SUCCESS)&&(errors>0)){
		errors--;
	}
	if (term2_lasterr!=SUCCESS) {
		hw_flags&=~Termo2_OK;
		term2_10_sec[ten_sec_index]=term2_10_sec[(ten_sec_index>0?ten_sec_index-1:11)];

	}else{
		term2_10_sec[ten_sec_index]=temperature/2;
		if (temperature==85*2) {
			if ((term2_10_sec[(ten_sec_index>0?ten_sec_index-1:11)]<70)||(term2_10_sec[(ten_sec_index>0?ten_sec_index-1:11)]>100)) {
				term2_10_sec[ten_sec_index]=term2_10_sec[(ten_sec_index>0?ten_sec_index-1:11)];
			}
		}
	}

	if (first_measure) {
		first_measure=0;
		for (errors=1;errors<12;errors++) {
			press_10_sec[errors]=press_10_sec[0];
			term1_10_sec[errors]=term1_10_sec[0];
			term2_10_sec[errors]=term2_10_sec[0];
		}
	}

	print_pressure(press_10_sec[ten_sec_index]);
	print_temp(term1_10_sec[ten_sec_index],0,term1_lasterr);
	print_temp(term2_10_sec[ten_sec_index],1,term2_lasterr);
#if HUMIDITY==21
	sht_lasterr=get_sht21_nohold(&sht_rh,&sht_t);
#endif
#if HUMIDITY==10
	if (sht_lasterr==SUCCESS) sht_lasterr=SHT10_calc_H();
	sht_t=SHT10_temperature();
	sht_rh=SHT10_humidity();
#endif
#if HUMIDITY>0
	print_humidity(sht_rh,sht_t,sht_lasterr);
#endif /* HUMIDITY */

	itoa(time.year+2000,&debug_str[0],10);
	itoa(time.month/10,&debug_str[4],10);
	itoa(time.month%10,&debug_str[5],10);
	itoa(time.day/10,&debug_str[6],10);
	itoa(time.day%10,&debug_str[7],10);
	debug_str[8]='T';
	itoa(time.hour/10,&debug_str[9],10);
	itoa(time.hour%10,&debug_str[10],10);
	itoa(time.min/10,&debug_str[11],10);
	itoa(time.min%10,&debug_str[12],10);
	itoa(time.sec/10,&debug_str[13],10);
	itoa(time.sec%10,&debug_str[14],10);
	debug(debug_str);
	debug("|");
	itoa(press_10_sec[ten_sec_index],debug_str,10);
	debug(debug_str);
	debug("|");
	itoa(term1_10_sec[ten_sec_index],debug_str,10);
	debug(debug_str);
	debug("|");
	itoa(term2_10_sec[ten_sec_index],debug_str,10);
	debug(debug_str);

#if HUMIDITY>0
	debug("|");
	itoa(sht_rh,debug_str,10);
	debug(debug_str);
	debug("|");
	itoa(sht_t,debug_str,10);
	debug(debug_str);
	debug("|");
	itoa(dew_point(sht_rh,sht_t),debug_str,10);
	debug(debug_str);
#endif
	debug("\r\n");

	ten_last_index=ten_sec_index;
	ten_sec_index++;
	if (ten_sec_index>11) ten_sec_index=0;

} //set_10_sec_avg()

void set_half_clock_avg() {
	uint32_t tmp_p=0;
	int16_t	tmp_t1=0,tmp_t2=0;
	uint8_t i;
	uint8_t * crc_p;
	value_array_t tmp_arr;

	for (i=0;i<12;i++) {
		tmp_p+=(uint32_t)press_10_sec[i];
		tmp_t1+=(int16_t)term1_10_sec[i];
		tmp_t2+=(int16_t)term2_10_sec[i];
	}

	half_clock_pressure[half_clock_index]=(uint16_t)(tmp_p/12);
	half_clock_t1[half_clock_index]=(int8_t)(tmp_t1/12);
	half_clock_t2[half_clock_index]=(int8_t)(tmp_t2/12);
	if (new_half_val) {
		for (i=1;i<HALF_CLK_ARR_SIZE;i++) {
			half_clock_pressure[i]=half_clock_pressure[0];
			half_clock_t1[i]=half_clock_t1[0];
			half_clock_t2[i]=half_clock_t2[0];
		}
	}

	if (new_half_val==0) {
		half_clock_index++;
		if (half_clock_index>(HALF_CLK_ARR_SIZE-1)) half_clock_index=0;
	}else{
		new_half_val=0;
	}
	//	print_delta_press(((uint16_t)(tmp_p/12))-(half_clock_pressure[half_clock_index]));

	tmp_p=0;tmp_t1=0;tmp_t2=0;
	for (i=0;i<HALF_CLK_ARR_SIZE;i++) {
		tmp_p+=half_clock_pressure[i];
		tmp_t1+=half_clock_t1[i];
		tmp_t2+=half_clock_t2[i];
	}

	tmp_arr.to_time=(time.unix_time/1800UL)*1800UL;
	tmp_arr.pressure=(uint16_t)(tmp_p/HALF_CLK_ARR_SIZE);
	tmp_arr.term1=(int8_t)(tmp_t1/HALF_CLK_ARR_SIZE);
	tmp_arr.term2=(int8_t)(tmp_t2/HALF_CLK_ARR_SIZE);
	tmp_arr.crc=0xffff;
	crc_p=(uint8_t *)&tmp_arr;
	for (i=0;i<sizeof(value_array_t)-2;i++) {
		tmp_arr.crc=_crc16_update(tmp_arr.crc,*crc_p);
		crc_p++;
	}
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { //Запретим прерывания и воостановим по окончании
		memcpy(&ram_array[time.position],&tmp_arr,sizeof(value_array_t));
	}
	GIFR|=(1<<INTF0);
	GICR|=(1<<INT0);
} //set_half_clock_avg()
